﻿using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;

using System.Text;

using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;

using System.Collections.Generic;


using System.Diagnostics;
using System.Diagnostics.Eventing;


namespace ProtocolWorkflows.OutboundDocumentslWF
{
    public sealed partial class OutboundDocumentslWF : StateMachineWorkflowActivity
    {



        #region  properties

        public string taskContentTypeId = "0x01080100FFbc98c2529347a5886b8d2576b954e3";

        public bool isTaskFinished = false;
        public bool isWorkflowFinished = false;
        public bool sendBackToRouter = false;

        public string LastOutcome = "";


        #endregion


        public OutboundDocumentslWF()
        {
            InitializeComponent();
        }

        public List<string> ApproversList = new List<string>();
        public int PreviousIndex = 0;
        public int CurrentIndex = 0;



        public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();

        private void InitializeApproversList_ExecuteCode(object sender, EventArgs e)
        {

            string initCode = "true";
            // Initiaize the Approvers list


        }

        private void InitializeApprovers_ExecuteCode(object sender, EventArgs e)
        {


            this.ApproversList = new List<string>();

            PreviousIndex = 0;
            CurrentIndex = 0;


            // TODO: Load the approvers from the request.

            //this.ApproversList.Add("8");
            //this.ApproversList.Add("6");
            //this.ApproversList.Add("7");


            SPListItem item = this.workflowProperties.Item;

            SPFieldUserValueCollection approvers = (SPFieldUserValueCollection)item[item.ParentList.Fields.GetFieldByInternalName("ProtocolApprovers").Id];


            if (approvers != null && approvers.Count > 0)
            {
                foreach (SPFieldUserValue approver in approvers)
                {

                    this.ApproversList.Add(approver.User.ID.ToString());
                }

            }

        }



        private void IsApproverListEmpty(object sender, ConditionalEventArgs e)
        {
            if (ApproversList.Count > 0)
                e.Result = false;
            else
                e.Result = true;

        }


        private void IsApprovalComplete(object sender, ConditionalEventArgs e)
        {
            if (CurrentIndex >= ApproversList.Count || this.isWorkflowFinished)
                e.Result = true;
            else
                e.Result = false;
        }

        private void SetApproverState_ExecuteCode(object sender, EventArgs e)
        {




            // Set the details for the task to be created.


        }

        public Guid createApprovalTask_TaskId1 = default(System.Guid);
        public SPWorkflowTaskProperties createApprovalTask_TaskProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();



        private void createApprovalTask_MethodInvoking(object sender, EventArgs e)
        {




            createApprovalTask_TaskId1 = Guid.NewGuid();



            SPUser approver = this.workflowProperties.Web.AllUsers.GetByID(int.Parse(this.ApproversList[CurrentIndex]));



            createApprovalTask_TaskProperties1.AssignedTo = approver.LoginName;


            string subject = "";
            string body = "";

            SetMailSubjectAndBody("OUTGOING_DOCUMENT_TASK_ASSIGNED", this.workflowProperties.Item, ref  subject, ref   body);

            SendEmail("OUTGOING_DOCUMENT_TASK_ASSIGNED", this.workflowProperties.Item, approver.LoginName, subject, body);




            createApprovalTask_TaskProperties1.Title = subject; // Resource1.ApprovalTask_Title;
            //createApprovalTask_TaskProperties1.Description = Resource1.ApprovalTask_Description;

            // Add the custom properties
            createApprovalTask_TaskProperties1.ExtendedProperties["TaskStage"] = "approver";
            createApprovalTask_TaskProperties1.ExtendedProperties["TargetListItemId"] = this.workflowProperties.Item.ID.ToString();
            createApprovalTask_TaskProperties1.ExtendedProperties["TargetListId"] = this.workflowProperties.Item.ParentList.ID.ToString();
            createApprovalTask_TaskProperties1.ExtendedProperties["LinkToItem"] = string.Format("{0}/{1}", this.workflowProperties.Web.Url, this.workflowProperties.Item.Url);


            //SendEmail("OUTGOING_DOCUMENT_TASK_ASSIGNED", this.workflowProperties.Item, approver.LoginName);


        }


        private void SendEmail(string messageCode, SPListItem item, string toLogin, string subject, string body)
        {

            string to = "";

            SPUser toUser = null;

            try
            {

                toUser = item.Web.AllUsers[toLogin];


                if (toUser != null)
                {

                    bool isEnabled = false;

                    GetEmailSettings(item, ref isEnabled);

                    if (isEnabled)
                    {
                        to = toUser.Email;

                        try
                        {
                            SPUtility.SendEmail(item.Web, true, true, to, subject, body);
                        }
                        catch (Exception sendMailException)
                        {

                            WriteError(sendMailException); ;

                        }

                    }


                }


            }
            catch (Exception sendMailException)
            {
                WriteError(sendMailException); ;

            }


        }

        private void SetMailSubjectAndBody(string messageCode, SPListItem item, ref string subject, ref string body)
        {



            try
            {
                SPList messagesList = item.Web.GetList(string.Format("{0}/Lists/{1}", item.Web.ServerRelativeUrl, "MailMessages"));


                StringBuilder queryCommand = new StringBuilder();

                queryCommand.Append("<Where>");
                queryCommand.Append("<Eq>");
                queryCommand.Append("<FieldRef Name=\"MessageCode\" />");
                queryCommand.Append(string.Format("<Value Type=\"Text\">{0}</Value>", messageCode));
                queryCommand.Append("</Eq>");
                queryCommand.Append("</Where>");

                SPQuery query = new SPQuery();
                query.Query = queryCommand.ToString();


                SPListItemCollection messages = messagesList.GetItems(query);

                if (messages != null && messages.Count > 0)
                {

                    SPListItem message = messages[0];

                    if (message[message.ParentList.Fields.GetFieldByInternalName("MessageSubject").Id] != null)
                    {
                        try
                        {
                            subject = message[message.ParentList.Fields.GetFieldByInternalName("MessageSubject").Id].ToString();

                        }
                        catch (SPException getMailSubjectAndBodyException)
                        {
                            WriteError(getMailSubjectAndBodyException);


                        }

                    }


                    if (message[message.ParentList.Fields.GetFieldByInternalName("MessageBodyText").Id] != null)
                    {
                        try
                        {
                            body = message[message.ParentList.Fields.GetFieldByInternalName("MessageBodyText").Id].ToString();



                        }
                        catch (SPException getMailSubjectAndBodyException)
                        {
                            WriteError(getMailSubjectAndBodyException);

                        }

                    }



                    if (!string.IsNullOrEmpty(subject))
                    {
                        try
                        {
                            subject = string.Format(subject, item.Title);
                        }
                        catch { ;}

                    }


                    if (!string.IsNullOrEmpty(body))
                    {
                        try
                        {
                            body = string.Format(body, item.Title);
                        }
                        catch { ;}

                    }


                }

            }
            catch (SPException getMailSubjectAndBodyException)
            {
                WriteError(getMailSubjectAndBodyException);

            }



        }


        private void GetEmailSettings(SPListItem item, ref bool isEnabled)
        {

            SPList configList = item.Web.GetList(string.Format("{0}/Lists/{1}", item.Web.ServerRelativeUrl, "LibraryConfiguration"));

            foreach (SPListItem configItem in configList.Items)
            {
                if (configItem[configItem.ParentList.Fields.GetFieldByInternalName("ListName").Id].ToString() == item.ParentList.Title)
                {
                    if (configItem[configItem.ParentList.Fields.GetFieldByInternalName("EmailEnabled").Id] != null)
                    {

                        try
                        {
                            isEnabled = (bool)configItem[configItem.ParentList.Fields.GetFieldByInternalName("EmailEnabled").Id];
                        }
                        catch (Exception GetRouterException)
                        {
                            WriteError(GetRouterException);
                        }
                    }
                    break;
                }

            }

        }


        private void WriteError(Exception ex)
        {

            EventLog LogToSystem = new EventLog();

            LogToSystem.Source = "SharePoint 2010 Protocols Library";
            LogToSystem.WriteEntry(ex.Message + " : " + ex.StackTrace, EventLogEntryType.Error);

        }


        public SPWorkflowTaskProperties onTaskChanged1_AfterProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChanged1_BeforeProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();


        private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e)
        {
            onTaskChanged1_BeforeProperties1 = onTaskChanged1.BeforeProperties;
            onTaskChanged1_AfterProperties1 = onTaskChanged1.AfterProperties;
        }


        private void IsTaskComplete(object sender, ConditionalEventArgs e)
        {
            if (onTaskChanged1_AfterProperties1.PercentComplete == 1F)
                e.Result = true;
            else
                e.Result = false;

        }

        private void codeActivity1_ExecuteCode(object sender, EventArgs e)
        {

            try
            {

                // Get the outcome from this task
                this.LastOutcome = (string)onTaskChanged1_AfterProperties1.ExtendedProperties[this.workflowProperties.TaskList.Fields["TaskOutcome"].Id];

                // If not approved then wf finishes
                if (this.LastOutcome != Resource1.Status_Approved)
                {
                    this.isWorkflowFinished = true;
                }

            }
            catch { ;}


            CurrentIndex++;
        }

        private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
        {

            string invokeString = "true";

        }

        private void SetFinalItemStatus_ExecuteCode(object sender, EventArgs e)
        {


            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                try
                {
                    using (SPSite site = new SPSite(this.workflowProperties.Item.Web.Url))
                    {
                        site.AllowUnsafeUpdates = true;

                        using (SPWeb web = site.OpenWeb())
                        {

                            web.AllowUnsafeUpdates = true;


                            SPListItem item = web.Lists[this.workflowProperties.Item.ParentList.ID].GetItemById(this.workflowProperties.Item.ID);


                            SPFieldBoolean isClosedField = (SPFieldBoolean)this.workflowProperties.Web.Fields.GetFieldByInternalName("IsClosed");
                            item[isClosedField.Title] = true;

                            SPFieldDateTime dateClosedField = (SPFieldDateTime)this.workflowProperties.Web.Fields.GetFieldByInternalName("CloseDate");
                            item[dateClosedField.Title] = DateTime.Now;

                            SPFieldChoice statusField = (SPFieldChoice)this.workflowProperties.Web.Fields.GetFieldByInternalName("DocumentStatus");
                            item[statusField.Title] = this.LastOutcome;


                            if (this.LastOutcome == Resource1.Status_Approved)
                            {
                                string protocolID = BuildProtocolID(item);

                                if (!string.IsNullOrEmpty(protocolID))
                                {
                                    item[item.ParentList.Fields.GetFieldByInternalName("ProtocolID").Id] = protocolID;
                                    item[item.ParentList.Fields.GetFieldByInternalName("ProtocolDate").Id] = DateTime.Now;
                                }
                            }

                            item.SystemUpdate();


                            // Send the final email

                            SPFieldUserValue submitterUser = (SPFieldUserValue)item[item.ParentList.Fields.GetFieldByInternalName("SentForProtocolBy").Id];
                            if (submitterUser != null)
                            {

                                string subject = "";
                                string body = "";
                                string to = submitterUser.User.Email;

                                if (this.LastOutcome == Resource1.Status_Approved)
                                {
                                    SetMailSubjectAndBody("OUTGOING_DOCUMENT_APPROVED", this.workflowProperties.Item, ref  subject, ref   body);
                                    SendEmail("OUTGOING_DOCUMENT_APPROVED", this.workflowProperties.Item, to, subject, body);
                                }
                                else if (this.LastOutcome == Resource1.Status_Rejected)
                                {
                                    SetMailSubjectAndBody("OUTGOING_DOCUMENT_REJECTED", this.workflowProperties.Item, ref  subject, ref   body);
                                    SendEmail("OUTGOING_DOCUMENT_REJECTED", this.workflowProperties.Item, to, subject, body);
                                }
                                else if (this.LastOutcome == Resource1.Status_Returned)
                                {
                                    SetMailSubjectAndBody("OUTGOING_DOCUMENT_RETURNED", this.workflowProperties.Item, ref  subject, ref   body);
                                    SendEmail("OUTGOING_DOCUMENT_RETURNED", this.workflowProperties.Item, to, subject, body);
                                }
                            }

                        }
                    }
                }
                catch (Exception codeException)
                {
                    WriteError(codeException);
                }
            });



        }


        private string BuildProtocolID(SPListItem item)
        {
            string protocolID = "";


            // Get the forumula for the list.

            SPList configList = item.Web.GetList(string.Format("{0}/Lists/{1}", item.Web.ServerRelativeUrl, "LibraryConfiguration"));

            foreach (SPListItem configItem in configList.Items)
            {

                if (configItem["ListName"].ToString() == item.ParentList.Title)
                {






                    if (configItem[configItem.ParentList.Fields.GetFieldByInternalName("Formula").Id] != null)
                    {

                        string formula = configItem[configItem.ParentList.Fields.GetFieldByInternalName("Formula").Id].ToString();

                        protocolID = formula;

                        int startPos = 0;
                        int endPos = 0;
                        string formulaString = "";



                        #region Replace "AUTOID" token - use the ID to avoid duplicate ids
                        try
                        {
                            if (protocolID.Contains("AUTOID"))
                            {


                                int id = 0;

                                try
                                {

                                    // Get any offset so we can start the number schema from any position
                                    id = int.Parse(configItem[configItem.ParentList.Fields.GetFieldByInternalName("IDOffset").Id].ToString());
                                }
                                catch { ;}


                                startPos = protocolID.IndexOf("AUTOID[");
                                endPos = protocolID.IndexOf("]", startPos + 1);

                                formulaString = protocolID.Substring(startPos, endPos - startPos + 1);

                                string padLen = formulaString.Replace("AUTOID[", "").Replace("]", "");

                                // Insert the replacement string

                                id = id + item.ID;

                                protocolID = protocolID.Replace(formulaString, id.ToString().PadLeft(int.Parse(padLen), '0'));
                            }
                        }
                        catch (Exception GetIdException)
                        {
                            WriteError(GetIdException);
                        }


                        #endregion

                        #region Replace "DATE" token
                        try
                        {
                            if (protocolID.Contains("DATE"))
                            {

                                startPos = protocolID.IndexOf("DATE[");
                                endPos = protocolID.IndexOf("]", startPos + 1);

                                formulaString = protocolID.Substring(startPos, endPos - startPos + 1);

                                string dateFormatString = formulaString.Replace("DATE[", "").Replace("]", "");

                                // Insert the replacement string
                                protocolID = protocolID.Replace(formulaString, DateTime.Today.ToString(dateFormatString));

                            }
                        }
                        catch (Exception GetIdException)
                        {
                            WriteError(GetIdException);
                        }

                        #endregion

                    }

                    break;
                }


            }


            return protocolID;
        }


        private string GetLoginName(SPListItem item, string columnName)
        {

            string loginName = "";

            var userValue = new SPFieldUserValue(item.Web, (string)item[columnName]);

            if (userValue != null && userValue.User != null)
            {
                loginName = userValue.User.LoginName;
            }
            else
            {
                SPGroup group = item.Web.Groups[userValue.LookupValue];

                if (group != null)
                    loginName = group.LoginName;
            }

            return loginName;
        }




    }
}
